/*  GPIO
GPIO1
GPIO2
GPIO4
GPIO5
GPIO6
GPIO7
GPIO8
GPIO9
GPIO10
GPIO11
GPIO12
GPIO13
GPIO14
GPIO15
GPIO16
GPIO17
GPIO18
GPIO21
GPIO35
GPIO36
GPIO37
GPIO38
GPIO39
GPIO40
GPIO41
GPIO42
GPIO45
GPIO46
GPIO47
GPIO48
GPIO49
GPIO50
GPIO51
GPIO52
GPIO53
GPIO54
GPIO55
GPIO56
*/
#include <Arduino.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <HTTPClient.h>
#include <HTTPUpdate.h>
#include <Update.h>
#include <ESPmDNS.h>
#include <ArduinoJson.h>
#include <vector>
#include <SPIFFS.h>
#include <mutex>
#include <ESP32Servo.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include "freertos/queue.h"
#include <esp_task_wdt.h>
#include "driver/ledc.h"
#include "freertos/timers.h"
#include <math.h>
#include <driver/mcpwm.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

#define BOARD_NAME "ESP32S3"// 开发板配置

#define GPIO_QUEUE_LENGTH 8// 队列长度
#define QUEUE_STATUS_WRITABLE  			0 //队员状态为可写，由USART（串口）写结束后改为 QUEUE_STATUS_READABLE （可读）。
#define QUEUE_STATUS_READABLE  			1 //队员状态为可读，由man或其他函数读取并处理结束后改为 QUEUE_STATUS_WRITABLE （可写）。
#define Q_LEN  			20//队列长度
#define U_LEN  			2048//队员长度
struct ops_queue {
  char c[U_LEN];
  bool s;
};
ops_queue ops_queueb[Q_LEN] = {};
u8_t q_readable_count = 0;//可读队员数
u8_t q_search_readable_i = 0;//用于寻找可读队员，找到就进入处理状态
u8_t q_search_writable_i = 0;//用于寻找可读队员，找到就进入写状态

typedef void (*func_ptr)(char* str);// 定义函数指针类型
typedef struct {//动态回调函数（高级用法），通过函数指针和全局结构体实现动态逻辑绑定
	void (*callback)(char *);
	char *param;
} dynamic_callback;
func_ptr fp = NULL;
unsigned int num_fp;

std::mutex mtx;  // 全局互斥锁
char* init_gpios_high = (char*)"1,";
//1,2,3,4,5,6,7,//  电磁铁
//12,21,13,14,15,16,17,18,//减速电机
char* init_gpios_low = (char*)"0,0|1|2|3|4|5|6|7|12|21|13|14|15|16|17|18|48";
//HardwareSerial MySerial(1); // 定义一个硬件串口对象，这里使用UART1 参数 1 表示使用UART1
//#define MY_TX_PIN 5 // 自定义的UART选择引脚
//#define MY_RX_PIN 6
const char* www_username = "admin";// 用户认证信息
const char* www_password = "esp32password";
const char* ssid = "DR";//adol-3447C6 WiFi配置 神的iphone  
const char* password = "qwert12345";// QWEqwe123  qwert12345
String firmware_version = "1.0.0";
String firmware_update_btn = "<p></p>";
String debug_info = "";
hw_timer_t *timer = NULL;// 定时器句柄
volatile bool timerFlag = false;//  volatile 变量，用于在ISR和主循环之间共享状态

//static TaskHandle_t isr_task_handle = NULL;// 定义中断任务句柄
//typedef struct {
//  gpio_num_t gpio_num;
//  char op_code[256];
//  volatile bool triggered;
//  TimerHandle_t debounce_timer;
//  bool interrupt_enabled;
//  bool trigger_wait;
//  uint8_t check_phase;          // 检查阶段：0=初始, 1-6=六次检查
//  uint32_t check_times[6];      // 记录每次检查的时间戳
//  int check_levels[6];          // 记录每次检查的电平
//} isr_struct;
//isr_struct isr_struct_b;
Servo servos[4]; // 4个舵机
AsyncWebServer server(80);// Web服务器配置
const char* host = "ESP32S3";
u8_t htttp_request_count = 0;

char *endptr_fp;//用于strtol函数调用后检查错误 if (endptr_fp == queue_a[queue_handling_i].c) {// 无有效数字//} else if (*endptr != '\0') {// 字符串含非数字字符（例如"abc"）//}
char *temp,*next_p,*temp_next_p;unsigned int functions_i;
static bool otaInProgress = false;//固件更新
static TaskHandle_t otaTaskHandle = NULL;//固件更新
static String otaFirmwareURL = "http://192.168.112.253/";// 全局变量存储URL，避免传递指针问题


bool checkFirmwareForUpdate() {//================================== 固件更新检查===========================
    HTTPClient http;
    http.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);  // 强制跟随
    http.setRedirectLimit(5); // 最多跟随5次重定向172.18.63.78
        http.begin(otaFirmwareURL + "version.txt");
        int httpCode = http.GET();Serial.println("checkFirmwareForUpdate()");
        Serial.println(httpCode);
        if (httpCode == HTTP_CODE_OK) {
            String firmware_version_n = http.getString();Serial.println(firmware_version_n);
            http.end();   
            if (firmware_version_n != firmware_version) {
                firmware_update_btn = "<button style=\"color:green\" onclick=\"location.href='/firmwareupdate'\">固件更新</button>";
                return true;
            }
        }
        firmware_update_btn = "";
        return false;
    }
void performOTAInTask(String url) {//============================== 固件更新 performOTAInTask==============
    Serial.println("OTA URL: " + url);
    HTTPClient http;
    http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
    http.setTimeout(54464);
    Serial.println("Attempting to connect to: " + url);// 调试：打印URL信息       
    bool beginSuccess = http.begin(url);// 使用正确的begin方法
    if (!beginSuccess) {
        Serial.println("HTTP begin failed in task");
        Serial.println("URL details:"); // 详细错误信息
        Serial.println("  Protocol: " + url.substring(0, url.indexOf(":")));
        Serial.println("  Host: " + url.substring(url.indexOf("://") + 3, url.indexOf("/", url.indexOf("://") + 3)));
        Serial.println("  Path: " + url.substring(url.indexOf("/", url.indexOf("://") + 3)));        
        return;
    }    
    Serial.println("HTTP connection established, sending GET request...");   
    int httpCode = http.GET();
    Serial.printf("HTTP response code: %d\r\n", httpCode);    
    if (httpCode != HTTP_CODE_OK) {
        Serial.printf("HTTP error in task: %d - %s\r\n", httpCode, http.errorToString(httpCode).c_str());
        http.end();
        return;
    }
    int contentLength = http.getSize();
    Serial.printf("Downloading %d bytes in task...\r\n", contentLength);
    if (contentLength <= 0) {
        Serial.println("Invalid content length");
        http.end();
        return;
    }
    if (!Update.begin(contentLength)) {
        Serial.printf("Update begin failed in task: %s\r\n", Update.errorString());
        http.end();
        return;
    }
    WiFiClient* stream = http.getStreamPtr();
    size_t written = 0;
    unsigned long lastProgress = 0;
    unsigned long lastWdtReset = millis();
    Serial.println("Starting firmware download...");
    while (http.connected() && written < contentLength) {
        // 定期喂狗和报告进度
        if (millis() - lastWdtReset > 2000) {
            esp_task_wdt_reset();
            lastWdtReset = millis();
        }
        if (millis() - lastProgress > 500) {
            int progress = (written * 100) / contentLength;
            Serial.printf("Progress: %d%%\r\n", progress);
            lastProgress = millis();
        }        
        if (stream->available()) {
            size_t available = stream->available();
            uint8_t buffer[512];
            size_t toRead = min(available, sizeof(buffer));
            size_t bytesRead = stream->readBytes(buffer, toRead);           
            if (bytesRead > 0) {
                size_t bytesWritten = Update.write(buffer, bytesRead);
                if (bytesWritten != bytesRead) {
                    Serial.printf("Write error: wrote %d, expected %d\r\n", bytesWritten, bytesRead);
                    break;
                }
                written += bytesWritten;
            }
        } else {
            vTaskDelay(50 / portTICK_PERIOD_MS);
        }
    }
    
    http.end();
    Serial.printf("Download completed: %d/%d bytes\r\n", written, contentLength);
    
    if (written == contentLength) {
        Serial.println("Finalizing update...");
        if (Update.end()) {
            Serial.println("OTA update completed successfully in task!");
            Serial.println("Rebooting in 3 seconds...");
            delay(3000);
            ESP.restart();
        } else {
            Serial.printf("Update finalization failed: %s\r\n", Update.errorString());
        }
    } else {
        Serial.println("Download incomplete");
    }
}
void otaTask(void *parameter) {//================================== 固件更新 otaTask=======================
    Serial.println("OTA task started on core " + String(xPortGetCoreID()));
    // 配置任务看门狗
    esp_task_wdt_init(120, false); // 2分钟超时
    esp_task_wdt_add(NULL);
    // 直接使用全局变量，避免参数传递问题
    performOTAInTask(otaFirmwareURL);
    // 清理
    esp_task_wdt_delete(NULL);
    otaInProgress = false;
    otaTaskHandle = NULL;
    vTaskDelete(NULL);
}
bool startOTAUpdate(String url) {//================================ 固件更新 startOTAUpdate================
    if (otaInProgress) {
        Serial.println("OTA already in progress");
        return false;
    }   
    if (!url.startsWith("http://") && !url.startsWith("https://")) {// 验证URL格式
        Serial.println("Invalid URL format. Must start with http:// or https://");
        return false;
    }   
    Serial.println("Starting OTA update with URL: " + url);  
    otaInProgress = true;
    otaFirmwareURL = url; // 存储到全局变量   
    BaseType_t result = xTaskCreatePinnedToCore(// 创建OTA任务（在核心1上运行）
        otaTask,
        "OTA_Task",
        16384, // 堆栈大小
        NULL,  // 不再传递参数
        2,     // 优先级
        &otaTaskHandle,
        1      // 核心1
    );    
    if (result != pdPASS) {
        Serial.println("Failed to create OTA task");
        otaInProgress = false;
        return false;
    }   
    Serial.println("OTA task created successfully");
    return true;
}
char *myStrsep(char *curr_p, const char *delim,char **next_p) {//== 自定义字符串截断========================
  if (NULL == curr_p || '\0' == *curr_p) {printf("debug myStrsep NULL == curr_p || '' == curr_p\r\n");*next_p = NULL;return curr_p;}
	//printf("debug *myStrsep(char *curr_p, const char *delim,char **next_p) S curr_p=%s delim=%s\r\n",curr_p,delim);
  char *end = curr_p + strcspn(curr_p, delim);
	*next_p = end + 1;
  if (*end == '\0') { *next_p = NULL;}
  *end = '\0';
  //printf("debug *myStrsep(char *curr_p, const char *delim,char **next_p) E curr_p=%s\r\n",curr_p);
	return curr_p;
}
void initGPIO(char *xb) {//======================================== 批量初始化GPIO==========================
  if (xb == NULL){printf("debug initGPIO(char *xb) xb == NULL\r\n");return;}
  printf("initGPIO(char *xb) S xb=%s \r\n",xb);
  char *level_str = myStrsep(xb, ",", &xb);// 解析电平值
  if (level_str == NULL){printf("debug initGPIO(char *xb) level_str == NULL\r\n");return;}
  u8_t level = (u8_t)strtol(level_str, &endptr_fp, 10);
  if (endptr_fp == level_str){printf("debug initGPIO(char *xb) endptr_fp == level_str\r\n");return;}// 转换失败，不是有效的数字 
  // 解析并初始化所有引脚
  char *pin_str; u8_t pin;
  while (xb) {
    pin_str = myStrsep(xb, "|", &xb);
    if (pin_str == NULL){printf("debug initGPIO(char *xb) pin_str == NULL\r\n");return;}
    pin = (u8_t)strtol(pin_str, &endptr_fp, 10);
    if (endptr_fp == level_str){printf("debug initGPIO(char *xb) endptr_fp == level_str\r\n");return;}// 转换失败，不是有效的数字 
    pinMode(pin, OUTPUT);
    digitalWrite(pin, level);
  }
  printf("debug initGPIO(char *xb) E\r\n");
}

//#include "driver/gpio.h"
//#include "freertos/timers.h"

typedef struct {
  gpio_num_t gpio_num;
  char op_code[256];
  volatile bool triggered;
  TimerHandle_t debounce_timer;
  bool interrupt_enabled;
  uint8_t check_phase;          // 检查阶段：0=初始, 1-6=六次检查
  uint32_t check_times[6];      // 记录每次检查的时间戳
  int check_levels[6];          // 记录每次检查的电平
  bool wait_interrupt;
} isr_struct;

isr_struct isr_struct_b;
static TaskHandle_t isr_task_handle = NULL;

// 六次电平检查防抖
void six_stage_debounce_check(isr_struct* isr_data) {
  int current_level = gpio_get_level(isr_data->gpio_num);
  uint8_t phase = isr_data->check_phase - 1; // 当前阶段索引
  
  // 记录时间和电平
  isr_data->check_times[phase] = esp_timer_get_time() / 1000; // 时间戳(ms)
  isr_data->check_levels[phase] = current_level;
  
  switch(isr_data->check_phase) {
    case 1: // 第一次检查（中断触发时）
      printf("[%d] Check 1: Level=%d\n", isr_data->gpio_num, current_level);
      
      if (current_level == 1) {
        isr_data->check_phase = 2;
        xTimerChangePeriod(isr_data->debounce_timer, pdMS_TO_TICKS(3), portMAX_DELAY);
        printf("Check 1 passed, Check 2 in 3ms\n");
      } else {
        printf("Check 1 failed, re-enabling interrupt\n");
        gpio_intr_enable(isr_data->gpio_num);
        isr_data->interrupt_enabled = true;
        isr_data->check_phase = 0;
      }
      break;
      
    case 2: // 第二次检查（3ms后）
      printf("[%d] Check 2: Level=%d (Time from Check 1: %dms)\n", 
             isr_data->gpio_num, current_level,
             isr_data->check_times[1] - isr_data->check_times[0]);
      
      if (current_level == 1) {
        isr_data->check_phase = 3;
        xTimerChangePeriod(isr_data->debounce_timer, pdMS_TO_TICKS(3), portMAX_DELAY);
        printf("Check 2 passed, Check 3 in 3ms\n");
      } else {
        printf("Check 2 failed, re-enabling interrupt\n");
        gpio_intr_enable(isr_data->gpio_num);
        isr_data->interrupt_enabled = true;
        isr_data->check_phase = 0;
      }
      break;
      
    case 3: // 第三次检查（6ms后）
      printf("[%d] Check 3: Level=%d (Time from Check 1: %dms)\n", 
             isr_data->gpio_num, current_level,
             isr_data->check_times[2] - isr_data->check_times[0]);
      
      if (current_level == 1) {
        isr_data->check_phase = 4;
        xTimerChangePeriod(isr_data->debounce_timer, pdMS_TO_TICKS(4), portMAX_DELAY);
        printf("Check 3 passed, Check 4 in 4ms\n");
      } else {
        printf("Check 3 failed, re-enabling interrupt\n");
        gpio_intr_enable(isr_data->gpio_num);
        isr_data->interrupt_enabled = true;
        isr_data->check_phase = 0;
      }
      break;
      
    case 4: // 第四次检查（10ms后）
      printf("[%d] Check 4: Level=%d (Time from Check 1: %dms)\n", 
             isr_data->gpio_num, current_level,
             isr_data->check_times[3] - isr_data->check_times[0]);
      
      if (current_level == 1) {
        isr_data->check_phase = 5;
        xTimerChangePeriod(isr_data->debounce_timer, pdMS_TO_TICKS(5), portMAX_DELAY);
        printf("Check 4 passed, Check 5 in 5ms\n");
      } else {
        printf("Check 4 failed, re-enabling interrupt\n");
        gpio_intr_enable(isr_data->gpio_num);
        isr_data->interrupt_enabled = true;
        isr_data->check_phase = 0;
      }
      break;
      
    case 5: // 第五次检查（15ms后）
      printf("[%d] Check 5: Level=%d (Time from Check 1: %dms)\n", 
             isr_data->gpio_num, current_level,
             isr_data->check_times[4] - isr_data->check_times[0]);
      
      if (current_level == 1) {
        isr_data->check_phase = 6;
        xTimerChangePeriod(isr_data->debounce_timer, pdMS_TO_TICKS(5), portMAX_DELAY);
        printf("Check 5 passed, Check 6 in 5ms\n");
      } else {
        printf("Check 5 failed, re-enabling interrupt\n");
        gpio_intr_enable(isr_data->gpio_num);
        isr_data->interrupt_enabled = true;
        isr_data->check_phase = 0;
      }
      break;
      
    case 6: // 第六次检查（20ms后）
      printf("[%d] Check 6: Level=%d (Time from Check 1: %dms)\n", 
             isr_data->gpio_num, current_level,
             isr_data->check_times[5] - isr_data->check_times[0]);
      
      // 分析所有检查结果
      bool all_checks_passed = true;
      for (int i = 0; i < 6; i++) {
        if (isr_data->check_levels[i] != 1) {
          all_checks_passed = false;
          break;
        }
      }
      
      if (all_checks_passed) {
        // 六次检查都通过，确认有效上升沿中断
        uint32_t total_duration = isr_data->check_times[5] - isr_data->check_times[0];
        printf("All six checks passed! Total duration: %dms, confirmed valid interrupt\n", total_duration);
        printf("Check history: %d,%d,%d,%d,%d,%d\n",
               isr_data->check_levels[0], isr_data->check_levels[1],
               isr_data->check_levels[2], isr_data->check_levels[3],
               isr_data->check_levels[4], isr_data->check_levels[5]);
        
        BaseType_t xHigherPriorityTaskWoken = pdFALSE;
        xTaskNotifyFromISR(isr_task_handle, 0, eNoAction, &xHigherPriorityTaskWoken);
        
        if (xHigherPriorityTaskWoken) {
          portYIELD_FROM_ISR();
        }
      } else {
        // 第六次检查失败或历史中有失败
        printf("Not all six checks passed, re-enabling interrupt\n");
        printf("Check history: %d,%d,%d,%d,%d,%d\n",
               isr_data->check_levels[0], isr_data->check_levels[1],
               isr_data->check_levels[2], isr_data->check_levels[3],
               isr_data->check_levels[4], isr_data->check_levels[5]);
        
        gpio_intr_enable(isr_data->gpio_num);
        isr_data->interrupt_enabled = true;
      }
      isr_data->check_phase = 0;
      break;
  }
}

// 防抖定时器回调函数
void debounce_timer_callback(TimerHandle_t xTimer) {
  isr_struct* isr_data = (isr_struct*)pvTimerGetTimerID(xTimer);
  six_stage_debounce_check(isr_data);
}

void IRAM_ATTR gpio_isr_handler(void* arg) {
  isr_struct* isr_structt = (isr_struct*)arg;
  printf("1\r\n");
  // 立即禁用中断，防止在防抖期间重复触发
  gpio_intr_disable(isr_structt->gpio_num);printf("2\r\n");
  isr_structt->interrupt_enabled = false;printf("3\r\n");
  
  // 设置第一次检查阶段
  isr_structt->check_phase = 1;printf("4\r\n");
  
  // 立即进行第一次电平检查（在ISR中直接检查）
  int current_level = gpio_get_level(isr_structt->gpio_num);printf("5\r\n");
  
  if (current_level == 1) {
    // 第一次检查通过，启动定时器进行3ms后第二次检查
    printf("ISR: Check 1 passed, starting Check 2 in 3ms\n");
    isr_structt->check_phase = 2;
    
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;printf("6\r\n");
    xTimerStartFromISR(isr_structt->debounce_timer, &xHigherPriorityTaskWoken);printf("7\r\n");
    
    if (xHigherPriorityTaskWoken) {
      portYIELD_FROM_ISR();printf("8\r\n");
    }
  } else {
    // 第一次检查失败，立即重新启用中断
    printf("ISR: Check 1 failed, immediately re-enabling interrupt\n");
    gpio_intr_enable(isr_structt->gpio_num);printf("9\r\n");
    isr_structt->interrupt_enabled = true;printf("10\r\n");
    isr_structt->check_phase = 0;printf("11\r\n");
  }
}

void interruptConfg(char *xb) {
  printf("interruptConfg started - Six-level check debounce configuration\n");
  
  // 解析GPIO编号和操作码
  char* endptr;
  isr_struct_b.gpio_num = (gpio_num_t)strtol(myStrsep(xb, "|",&xb), &endptr, 10);
  strncpy(isr_struct_b.op_code, xb, sizeof(isr_struct_b.op_code)-1);
  isr_struct_b.op_code[sizeof(isr_struct_b.op_code)-1] = '\0';
  isr_struct_b.triggered = false;
  isr_struct_b.interrupt_enabled = false;
  isr_struct_b.check_phase = 0;
  memset(isr_struct_b.check_times, 0, sizeof(isr_struct_b.check_times));
  memset(isr_struct_b.check_levels, 0, sizeof(isr_struct_b.check_levels));
  
  // 创建防抖定时器（初始周期设为3ms）
  isr_struct_b.debounce_timer = xTimerCreate(
    "debounce_timer",
    pdMS_TO_TICKS(3),  // 初始3ms
    pdFALSE,           // 单次定时器
    (void*)&isr_struct_b,
    debounce_timer_callback
  );
  
  if (isr_struct_b.debounce_timer == NULL) {
    printf("Error: Failed to create debounce timer\n");
    return;
  }
  
  printf("Configure GPIO %d, rising edge trigger, Opcode: %s\n", 
         isr_struct_b.gpio_num, isr_struct_b.op_code);
  printf("Debounce mode: Six-level check (immediate + 3ms + 6ms + 10ms + 15ms + 20ms)\n");
  printf("Total debounce time: 20ms, Check interval: 3-5ms\n");
  
  // 配置GPIO为上升沿触发
  gpio_config_t io_conf;
  io_conf.intr_type = GPIO_INTR_POSEDGE;      // 上升沿触发
  io_conf.mode = GPIO_MODE_INPUT;
  io_conf.pin_bit_mask = (1ULL << isr_struct_b.gpio_num);
  io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE; // 启用下拉电阻
  io_conf.pull_up_en = GPIO_PULLUP_DISABLE;    // 禁用上拉电阻
  
  esp_err_t ret = gpio_config(&io_conf);
  if (ret != ESP_OK) {
    printf("GPIO configuration failed: %d\n", ret);
    return;
  }
  
  // 添加中断处理程序
  ret = gpio_isr_handler_add(isr_struct_b.gpio_num, gpio_isr_handler, &isr_struct_b);
  if (ret != ESP_OK) {
    printf("Failed to add interrupt handler: %d\n", ret);
    return;
  }
  
  // 启用中断
  gpio_intr_enable(isr_struct_b.gpio_num);
  isr_struct_b.interrupt_enabled = true;
  isr_struct_b.wait_interrupt  = true;
  printf("interruptConfg completed - Six-level check debounce enabled\n");
  printf("wait interrupt\r\n");
  while(isr_struct_b.wait_interrupt){printf(".");delay(2500);}
}

// 获取详细的检查历史
void get_detailed_check_history() {
  printf("Six-check detailed history:\n");
  printf("  GPIO: %d, Interrupt enabled: %s, Current phase: %d\n", 
         isr_struct_b.gpio_num,
         isr_struct_b.interrupt_enabled ? "Yes" : "No",
         isr_struct_b.check_phase);
  
  if (isr_struct_b.check_phase > 0) {
    printf("  Check records:\n");
    for (int i = 0; i < isr_struct_b.check_phase; i++) {
      printf("    Check %d: %dms - Level=%d\n", 
             i+1, isr_struct_b.check_times[i], isr_struct_b.check_levels[i]);
    }
    
    // 计算时间间隔
    if (isr_struct_b.check_phase > 1) {
      printf("  Time intervals:\n");
      for (int i = 1; i < isr_struct_b.check_phase; i++) {
        uint32_t interval = isr_struct_b.check_times[i] - isr_struct_b.check_times[i-1];
        printf("    Check %d to %d: %dms\n", i, i+1, interval);
      }
    }
  }
}

// 分析信号质量
void analyze_signal_quality() {
  if (isr_struct_b.check_phase == 0) {
    printf("No check history available\n");
    return;
  }
  
  int high_count = 0;
  for (int i = 0; i < isr_struct_b.check_phase; i++) {
    if (isr_struct_b.check_levels[i] == 1) {
      high_count++;
    }
  }
  
  float success_rate = (float)high_count / isr_struct_b.check_phase * 100;
  printf("Signal quality analysis: %d/%d high levels (%.1f%%)\n", 
         high_count, isr_struct_b.check_phase, success_rate);
  
  if (success_rate < 100.0) {
    printf("Warning: Signal has jitter or interference\n");
  } else {
    printf("Signal quality excellent\n");
  }
}

// 清理函数
void interrupt_cleanup() {
  if (isr_struct_b.debounce_timer != NULL) {
    xTimerDelete(isr_struct_b.debounce_timer, portMAX_DELAY);
    isr_struct_b.debounce_timer = NULL;
  }
  
  if (isr_struct_b.gpio_num < GPIO_NUM_MAX && isr_struct_b.interrupt_enabled) {
    gpio_intr_disable(isr_struct_b.gpio_num);
    gpio_isr_handler_remove(isr_struct_b.gpio_num);
    isr_struct_b.interrupt_enabled = false;
  }
  
  isr_struct_b.check_phase = 0;
  memset(isr_struct_b.check_times, 0, sizeof(isr_struct_b.check_times));
  memset(isr_struct_b.check_levels, 0, sizeof(isr_struct_b.check_levels));
  
  printf("Interrupt resources cleaned up\n");
}

void IRAM_ATTR onTimer() {//========= 中断服务程序 (ISR)必须保持简短！不能使用delay(), millis(), Serial.print()等复杂或慢速函数。
  //timerFlag = true; // 仅仅设置一个标志位
  digitalWrite(48, !digitalRead(48)); // 翻转LED状态
}
void setOneShotTimer(char * seconds) {//=========================== 设置单次定时器中断======================
  uint32_t d_t = strtoul(seconds, nullptr, 10);
  if (timer != NULL) {// 如果定时器已存在，先停止并删除
    timerAlarmDisable(timer);
    timerDetachInterrupt(timer);
    timerEnd(timer);
    timer = NULL;
  }
  timer = timerBegin(0, 80, true); //初始化定时器，使用定时器0，分频系数80，向上计数
  timerAttachInterrupt(timer, &onTimer, true);  // 附加中断到定时器
  uint64_t microseconds = (uint64_t)d_t * 1000000;// 设置定时器值（秒转换为微秒）
  timerAlarmWrite(timer, microseconds, false); // 第三个参数false表示单次触发
  //timerStartTime = millis();// 记录启动时间
  timerAlarmEnable(timer);// 启用定时器警报
  Serial.printf("Timer X set for %lu seconds\r\n", d_t);
}
void delayMs(char *xb){//========================================== 毫秒级延时===============================
    unsigned long seconds = strtoul(xb, &endptr_fp, 10);   
    if (endptr_fp == xb || *endptr_fp != '\0' || seconds == 0 || seconds > 1000) {
        printf("delayMs Invalid input! Use 1-1000 \r\n");
        return;
    }
		delay(seconds);
}
void delayXsecond(char *xb){//===================================== 秒级延时===============================
	unsigned int delay_time = strtol(xb, &endptr_fp, 10);
	unsigned int i=0;
	for(i=0;i<delay_time;i++){
		delay(1000);
	}
	printf("delayXsecond|%d\r\n",delay_time);
}
void initSPIFFS() {//============================================== 初始化文件系统==========================
  if (!SPIFFS.begin(true)) {Serial.println("Unable to mount SPIFFS file system");return;}
  Serial.println("SPIFFS file system mounted");
}
int writeDatab(String fl_name,String fl_c){//====================== 将数据写入SPI Flash内存=================
    File file = SPIFFS.open("/" + fl_name, FILE_WRITE);
    if (!file) {Serial.println("Failed to open file for writing");return 0;}
    file.print(fl_c);
    Serial.println(fl_c);
    file.close();return 1;
}
JsonDocument readData(char* fl){//================================= 加载板载SPI Flash内存数据===============
  JsonDocument doc;
  File file = SPIFFS.open(fl, FILE_READ);
  if (!file) {Serial.println("Failed to open file for writing"); doc["b"] = "x";return doc;}
  //File configFile = SPIFFS.open("/config.json", "r");
  DeserializationError error = deserializeJson(doc, file);
  file.close();
  if (error) {Serial.print("JSON解析错误: ");Serial.println(error.c_str());doc["b"] = "x";return doc;}
  return doc;
}
void gpioOutLowHigh(char *pin_level){//============================ GPIO输出===============================
  //pin_level = "pin1|level,pin2|level,pin3level......";0|0,1|0,2|0,3|1,4|0,5|1.......  
  if (pin_level == NULL){printf("debug gpioOutLowHigh(char *pin_level) pin_level == NULL\r\n");return;}
  printf("gpioOutLowHigh S pin_level %s\r\n",pin_level);
  int pin = 0, leveb = 0,i=0;  char* p_l,*p_s;
  while(pin_level){
    if (NULL == (p_l = myStrsep(pin_level, ",",&pin_level))){printf("debug gpioOutLowHigh(char *pin_level) p_l == NULL\r\n");return;}
    if (NULL == (p_s = myStrsep(p_l, "|",&p_l))){printf("debug gpioOutLowHigh(char *pin_level) p_s == NULL\r\n");return;}
    pin = strtol(p_s,&endptr_fp, 10);if (endptr_fp == p_s){printf("debug initGPIO(char *xb) endptr_fp == p_s\r\n");return;}// 转换失败，不是有效的数字 
    if (p_l == NULL){printf("debug gpioOutLowHigh(char *pin_level) p_l == NULL\r\n");return;}
    leveb = strtol(p_l,&endptr_fp, 10);if (endptr_fp == p_l){printf("debug initGPIO(char *xb) endptr_fp == p_l\r\n");return;}// 转换失败，不是有效的数字    
    pinMode(pin, OUTPUT);
    digitalWrite(pin, leveb);
  }
  printf("gpioOutLowHigh E\r\n");
}
void initWiFi() {//================================================ 初始化WiFi连接==========================
  Serial.println("\nConnecting to WiFi...");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  WiFi.setHostname(host);// 设置主机名
  uint8_t dots = 0;
  while (WiFi.status() != WL_CONNECTED) {// 显示连接进度
    delay(500);
    Serial.print(".");
    if (++dots > 40) {
      Serial.println("\nConnection timeout, try reconnecting...");      
      WiFi.reconnect();
      dots = 0;
    }
  }
  Serial.println("\nWiFi is connected!");printf("WiFi ssid %s:\r\n",ssid);
  Serial.print("IP address:");
  Serial.println(WiFi.localIP().toString());
  Serial.print("Signal strength:");
  Serial.print(map(WiFi.RSSI(), -100, -40, 0, 100));
  Serial.println("");
}
void initMDNS() {//================================================ MDNS初始化=============================
  if (!MDNS.begin(host)) {
    Serial.println("MDNS startup failed!");
    return;
  }
  MDNS.addService("http", "tcp", 80);
  Serial.print("MDNS service started:http://");
  Serial.print(host);
  Serial.println(".local");
}
void setElectromagnet(char *xb) {//================================ 电磁铁控制函数==========================
  int gp_i = strtol(myStrsep(xb, "|",&xb), &endptr_fp, 10); printf("gp_i %d\r\n",gp_i);
  //int stateb = strtol(xb, &endptr_fp, 10); printf("stateb %d\r\n",stateb);
  //debug_info = gp_i+ stateb;
  //debug_info = String(gp_i) + "|" + String(stateb);
  if(gp_i >= 1 && gp_i <= 7) {
    digitalWrite(gp_i,HIGH);//LOW
    delayMs((char *)"500");
    digitalWrite(gp_i,LOW);
  }
  printf("setElectromagnet\r\n");
}
void setMotor(char *xb) {// ======================================= 减速电机控制函数direction: 0=======停止, 1=正转, 2=反转
  printf("setMotor S xb=%s\r\n",xb);
  int motor_pin_a = strtol(myStrsep(xb, "|",&xb), &endptr_fp, 10); printf("motor_pin_a %d\r\n",motor_pin_a);
  int motor_pin_b = strtol(myStrsep(xb, "|",&xb), &endptr_fp, 10); printf("motor_pin_b %d\r\n",motor_pin_b);
  int directionb = strtol(xb, &endptr_fp, 10); printf("directionb %d\r\n",directionb);
  digitalWrite(motor_pin_a, directionb == 1 ? HIGH : LOW);
  digitalWrite(motor_pin_b, directionb == 2 ? HIGH : LOW);
  debug_info = String(motor_pin_a) + "|" + String(motor_pin_b) + "|" + String(directionb);
  printf("setMotor E\r\n");
}
void smoothMoveServo(char *xb) {// ================================ 舵机控制函数(int servo_pin, int target_angleb,min_angle,max_angle)8_90_0_0_0_270
  if('\0' == *xb || NULL ==xb){printf("smoothMoveServo(char *xb) '\0' == *xb || NULL ==xb");return;}
  printf("smoothMoveServo(char *xb) S xb=%s\r\n",xb);
  int servo_i = 0, target_angle = 0,min_angle=0,max_angle;char* servo_i_str,*target_angle_str,*min_angle_str;
  if (NULL == (servo_i_str = myStrsep(xb, "|",&xb))){printf("debug smoothMoveServo(char *xb) servo_i_str == NULL\r\n");return;}
  servo_i = strtol(servo_i_str,&endptr_fp, 10);if (endptr_fp == servo_i_str){printf("debug smoothMoveServo(char *xb) endptr_fp == servo_i_str\r\n");return;}// 转换失败，不是有效的数字 
  if (NULL == (target_angle_str = myStrsep(xb, "|",&xb))){printf("debug smoothMoveServo(char *xb) target_angle_str == NULL\r\n");return;}
  target_angle = strtol(target_angle_str,&endptr_fp, 10);if (endptr_fp == target_angle_str){printf("debug smoothMoveServo(char *xb) endptr_fp == target_angle_str\r\n");return;}// 转换失败，不是有效的数字 
  if (NULL == (min_angle_str = myStrsep(xb, "|",&xb))){printf("debug smoothMoveServo(char *xb) min_angle_str == NULL\r\n");return;}
  min_angle = strtol(min_angle_str,&endptr_fp, 10);if (endptr_fp == min_angle_str){printf("debug smoothMoveServo(char *xb) endptr_fp == min_angle_str\r\n");return;}// 转换失败，不是有效的数字 
  if (NULL == xb){printf("debug smoothMoveServo(char *xb) xb(max_angle_str) == NULL\r\n");return;}
  max_angle = strtol(xb,&endptr_fp, 10);if (endptr_fp == xb){printf("debug smoothMoveServo(char *xb) endptr_fp == xb(max_angle_str)\r\n");return;}// 转换失败，不是有效的数字
  servos[servo_i].write(constrain(target_angle, min_angle, max_angle));
  debug_info = String(servo_i) + "|" + String(target_angle) + "|" + String(min_angle) + "|" + String(max_angle);
  printf("smoothMoveServo(char *xb) S servo_i=%d target_angle=%d min_angle=%d max_angle=%d\r\n",servo_i,target_angle,min_angle,max_angle);
} 

typedef float (*EasingFunction)(float t);//舵机缓动函数类型
float easeLinear(float t) {return t;}// 线性缓动
float easeInQuad(float t) {return t * t;}// 二次方缓入
float easeOutQuad(float t) {return 1 - (1 - t) * (1 - t);}// 二次方缓出
float easeInOutQuad(float t) {return t < 0.5 ? 2 * t * t : 1 - pow(-2 * t + 2, 2) / 2;}// 二次方缓入缓出
float easeInCubic(float t) {return t * t * t;}// 三次方缓入
float easeOutCubic(float t) {return 1 - pow(1 - t, 3);}// 三次方缓出
float easeOutElastic(float t) {// 弹性缓动
  float c4 = (2 * M_PI) / 3;
  return t == 0 ? 0 : t == 1 ? 1 : pow(2, -10 * t) * sin((t * 10 - 0.75) * c4) + 1;
}
float easeInOutSine(float t) {return -(cos(M_PI * t) - 1) / 2;}
float easeInOutCirc(float t) {
    return t < 0.5
        ? (1 - sqrt(1 - pow(2 * t, 2))) / 2
        : (sqrt(1 - pow(-2 * t + 2, 2)) + 1) / 2;
}
float easeInOutCubic(float t) {
    return t < 0.5 ? 4 * t * t * t : 1 - pow(-2 * t + 2, 3) / 2;
}
float current_angles[4] = {0, 0, 0, 0};
void smoothMove(int servo_i, int target_angle, int min_angle, int max_angle, int duration_ms, EasingFunction easingFunc) {// 平滑移动函数
    target_angle = constrain(target_angle, min_angle, max_angle);// 约束目标角度
    int start_angle = current_angles[servo_i];
    if(start_angle == target_angle) return;// 如果已经在目标位置，直接返回
    int steps = duration_ms / 15; // 每15ms一步
    if(steps < 1) steps = 1;
    for(int i = 0; i <= steps; i++) {
        float progress = (float)i / (float)steps;
        float eased_progress = easingFunc(progress);
        int current_pos = start_angle + (target_angle - start_angle) * eased_progress;
        servos[servo_i].write(current_pos);
        delay(15);
    }
    current_angles[servo_i] = target_angle;
}
void liquidSafeMove(int servo_i, int target_angle, int min_angle, int max_angle, int duration_ms = 0, bool useSine = true) {
    target_angle = constrain(target_angle, min_angle, max_angle);
    int start_angle = current_angles[servo_i];
    if(start_angle == target_angle) return;
    int angle_diff = abs(target_angle - start_angle);
    // === 为液体搬运特别设计的超慢速时间计算 ===
    if(duration_ms <= 0) {
        // 保守计算：每10度需要2-3秒，避免惯性导致液体晃动
        duration_ms = max(4000, angle_diff * 250); // 最少4秒，每度250ms
        // 如果是大角度移动（超过90度），额外增加时间
        if(angle_diff > 90) { duration_ms = duration_ms * 1.5;}
        printf("自动计算移动时间: %d度 -> %dms (%.1f秒)\n",  angle_diff, duration_ms, duration_ms/1000.0);
    } else {
        // 用户指定时间，但检查是否过短
        int min_safe_time = max(3000, angle_diff * 150); // 安全最小时间
        if(duration_ms < min_safe_time) {
            printf("警告: 设置时间%dm过短，液体可能洒出，已调整为安全时间%dm\n", duration_ms, min_safe_time);
            duration_ms = min_safe_time;
        }
    }
    printf("液体安全移动: 舵机[%d] %d° -> %d°, 时间: %.1f秒\n", servo_i, start_angle, target_angle, duration_ms/1000.0);
    unsigned long start_time = millis();
    int steps = max(10, duration_ms / 50); // 每50ms一步，保证足够平滑
    for(int i = 0; i <= steps; i++) {
        float progress = (float)i / (float)steps;
        float eased_progress = useSine ? easeInOutSine(progress) : easeInOutCubic(progress); 
        int current_pos = start_angle + (target_angle - start_angle) * eased_progress;
        servos[servo_i].write(current_pos); 
        // 精确延迟控制
        unsigned long elapsed = millis() - start_time;
        unsigned long expected_time = (duration_ms * i) / steps; 
        if(elapsed < expected_time) {
            unsigned long remaining = expected_time - elapsed;
            if(remaining > 10) {
                delay(remaining - 5); // 稍微提前一点，留出计算时间
            }
        } 
        // 每10%进度输出一次信息
        if(i % (steps/10) == 0) {
            printf("进度: %d%%, 当前角度: %d°\n", (i*100)/steps, current_pos);
        }
    }
    // 最终位置确认
    servos[servo_i].write(target_angle);
    current_angles[servo_i] = target_angle;
    unsigned long actual_time = millis() - start_time;
    printf("液体安全移动完成! 实际用时: %.1f秒\n", actual_time/1000.0);
}
void smoothMoveServob(char *xb) {
    if('\0' == *xb || NULL == xb) {printf("smoothMoveServo: Empty or NULL input\r\n");return;}
    printf("smoothMoveServo: xb=%s\r\n", xb);
    int servo_i = 0, target_angle = 0, min_angle = 0, max_angle = 0, duration = 500;
    int use_sine = 1; // 默认使用最平滑的sine缓动
    char* token;
    // 解析参数：servo_i|target_angle|min_angle|max_angle|duration(可选)
    if (NULL == (token = myStrsep(xb, "|", &xb))) return;
    servo_i = strtol(token, &endptr_fp, 10);
    if (NULL == (token = myStrsep(xb, "|", &xb))) return;
    target_angle = strtol(token, &endptr_fp, 10);
    if (NULL == (token = myStrsep(xb, "|", &xb))) return;
    min_angle = strtol(token, &endptr_fp, 10);
    if (NULL == (token = myStrsep(xb, "|", &xb))) return;
    max_angle = strtol(token, &endptr_fp, 10);
    if (NULL != (token = myStrsep(xb, "|", &xb))) {// 可选参数：移动时间（毫秒）
        duration = strtol(token, &endptr_fp, 10);
    }
    // 可选参数：是否使用sine缓动（1=是，0=使用cubic）
    if (NULL != (token = myStrsep(xb, "|", &xb))) {
        use_sine = strtol(token, &endptr_fp, 10);
    }
    // 验证参数
    if (servo_i < 0 || servo_i >= 4) {printf("Error: Invalid servo index %d\r\n", servo_i);return;}
    if (min_angle >= max_angle) {printf("Error: Invalid angle range %d-%d\r\n", min_angle, max_angle);return;}
    target_angle = constrain(target_angle, min_angle, max_angle);
    liquidSafeMove(servo_i, target_angle, min_angle, max_angle, duration, use_sine);
    servos[servo_i].detach();
    //smoothMove(servo_i, target_angle, min_angle, max_angle, duration, easeOutElastic);// 使用缓动函数进行平滑移动（这里使用easeInOutQuad）
    debug_info = String(servo_i) + "|" + String(target_angle) + "|" + String(min_angle) + "|" + String(max_angle) + "|" + String(duration);
    printf("Servo[%d] smoothly moved to %d in %dms\r\n", servo_i, target_angle, duration);
}
//步进电机控制
#define STEPPER_PWM_PIN 38     // 引脚定义// 脉冲引脚
#define STEPPER_DIR_PIN 39     // 方向引脚
#define STEPPER_ENABLE_PIN 40  // 使能引脚
#define MIN_FREQUENCY 10       // 频率范围// 最小频率
#define MAX_FREQUENCY 15000    // 最大频率
void initStepper() {//========================================================= 初始化步进电机
    pinMode(STEPPER_PWM_PIN, OUTPUT);
    pinMode(STEPPER_DIR_PIN, OUTPUT);
    pinMode(STEPPER_ENABLE_PIN, OUTPUT);
    
    digitalWrite(STEPPER_PWM_PIN, LOW);
    digitalWrite(STEPPER_DIR_PIN, 1); // 默认正转
    digitalWrite(STEPPER_ENABLE_PIN, HIGH); // 默认禁用电机
    
    printf("Stepper motor initialized\n");
}
void generatePulses(unsigned long frequency, unsigned long duration_ms) {//==== 生成指定频率的脉冲，持续指定时间============
    if (frequency == 0) {printf("Error: Frequency cannot be 0\n");return;}
    printf("Generating %lu Hz for %lu ms\n", frequency, duration_ms);
    unsigned long period_us = 1000000 / frequency; // 周期（微秒）
    unsigned long half_period_us = period_us / 2;
    unsigned long start_time = millis();
    unsigned long end_time = start_time + duration_ms;
    unsigned long pulse_count = 0;
    while (millis() < end_time) {
        digitalWrite(STEPPER_PWM_PIN, HIGH);
        delayMicroseconds(half_period_us);
        digitalWrite(STEPPER_PWM_PIN, LOW);
        delayMicroseconds(half_period_us);
        pulse_count++;
    }
    printf("Pulse generation completed - Total pulses: %lu\n", pulse_count);
}
void linearAccelerate(int start_freq, int target_freq, int duration_ms) {//==== 线性加速 - 使用简单的for循环===============
    printf("Linear acceleration: %d Hz -> %d Hz over %d ms\n", start_freq, target_freq, duration_ms);
    int freq_range = target_freq - start_freq;// 计算频率步长
    int steps = 100; // 加速步数
    int freq_step = freq_range / steps;
    int step_time = duration_ms / steps;// 每步的时间
    for(int i = 0; i <= steps; i++) {
        int current_freq = start_freq + (freq_step * i);
        // 确保频率在合理范围内
        if (current_freq < MIN_FREQUENCY) current_freq = MIN_FREQUENCY;
        if (current_freq > MAX_FREQUENCY) current_freq = MAX_FREQUENCY;
        printf("Acceleration step %d/%d: %d Hz for %d ms\n", i, steps, current_freq, step_time);
        generatePulses(current_freq, step_time);
    }
    printf("Linear acceleration completed\n");
}
void linearDecelerate(int start_freq, int target_freq, int duration_ms) {//==== 线性减速 - 使用简单的for循环===============
    printf("Linear deceleration: %d Hz -> %d Hz over %d ms\n", start_freq, target_freq, duration_ms);
    int freq_range = start_freq - target_freq;// 计算频率步长
    int steps = 100; // 减速步数
    int freq_step = freq_range / steps;
    int step_time = duration_ms / steps;// 每步的时间
    for(int i = 0; i <= steps; i++) {
        int current_freq = start_freq - (freq_step * i);
        // 确保频率在合理范围内
        if (current_freq < MIN_FREQUENCY) current_freq = MIN_FREQUENCY;
        if (current_freq > MAX_FREQUENCY) current_freq = MAX_FREQUENCY; 
        printf("Deceleration step %d/%d: %d Hz for %d ms\n", i, steps, current_freq, step_time);
        generatePulses(current_freq, step_time);
    }
    printf("Linear deceleration completed\n");
}
void controlStepperSequence(char *sequence) {//================================ 线性加速/减速步进电机控制函数===============
    if('\0' == *sequence || NULL == sequence) {
        printf("controlStepperSequence: Empty sequence\n");
        return;
    }
    printf("Stepper motor sequence: %s\n", sequence);
    // 解析序列参数
    int params[14];
    char* token;
    int param_count = 0;
    char* seq_ptr = sequence;
    while(NULL != (token = myStrsep(seq_ptr, "|", &seq_ptr)) && param_count < 14) {
        params[param_count] = strtol(token, &endptr_fp, 10);
        param_count++;
    }
    if(param_count != 14) {
        printf("Error: Expected 11 parameters, but received %d\n", param_count);
        return;
    }
//参数
  int pin_en = params[0];
  int pin_dir = params[1];
  int pin_pwm = params[2];
  int dir1 = params[3];
  int accel_time1 = params[4];
  int target_speed1 = params[5];
  int run_time1 = params[6];
  int decel_time1 = params[7];
  int rest_time1 = params[8];
  int dir2 = params[9];
  int accel_time2 = params[10];
  int target_speed2 = params[11];
  int run_time2 = params[12];
  int decel_time2 = params[13];
  printf("Parsed: pin_en%d|pin_dir%d|pin_pwm%d|Dir%d|Accel%d|Speed%d|Run%d|Decel%d|Rest%d|Dir%d|Accel%d|Speed%d|Run%d|Decel%d\n",
           pin_en,pin_dir,dir1,pin_pwm,accel_time1,target_speed1,run_time1,decel_time1,rest_time1,
           dir2,accel_time2,target_speed2,run_time2,decel_time2);
    
    digitalWrite(STEPPER_ENABLE_PIN, LOW);// 使能电机
    
    // 第一阶段
    printf("=== Phase 1 ===\n");
    
    // 设置方向
    digitalWrite(STEPPER_DIR_PIN, dir1);
    printf("Direction: %s\n", dir1 ? "Forward" : "Reverse");
    
    // 加速阶段 - 使用线性加速
    if(accel_time1 > 0 && target_speed1 > 0) {
        int target_freq = target_speed1 * (MAX_FREQUENCY / 255.0);
        linearAccelerate(MIN_FREQUENCY, target_freq, accel_time1 * 1000);
    }
    
    // 匀速运行阶段
    if(run_time1 > 0 && target_speed1 > 0) {
        int frequency = target_speed1 * (MAX_FREQUENCY / 255.0);
        printf("Constant speed: %d Hz for %d seconds\n", frequency, run_time1);
        generatePulses(frequency, run_time1 * 1000);
    }
    
    // 减速阶段 - 使用线性减速
    if(decel_time1 > 0 && target_speed1 > 0) {
        int start_freq = target_speed1 * (MAX_FREQUENCY / 255.0);
        linearDecelerate(start_freq, MIN_FREQUENCY, decel_time1 * 1000);
    }
    
    // 休息阶段
    if(rest_time1 > 0) {
        printf("Resting for %d seconds\n", rest_time1);
        digitalWrite(STEPPER_ENABLE_PIN, HIGH);// 禁用电机
        delay(rest_time1 * 1000);
        digitalWrite(STEPPER_ENABLE_PIN, LOW);// 使能电机
    }
    
    printf("=== Phase 1 Completed ===\n");
    
    // 第二阶段
    printf("=== Phase 2 ===\n");
    
    // 设置方向
    digitalWrite(STEPPER_DIR_PIN, dir2);
    printf("Direction: %s\n", dir2 ? "Forward" : "Reverse");
    
    // 加速阶段 - 使用线性加速
    if(accel_time2 > 0 && target_speed2 > 0) {
        int target_freq = target_speed2 * (MAX_FREQUENCY / 255.0);
        linearAccelerate(MIN_FREQUENCY, target_freq, accel_time2 * 1000);
    }
    
    // 匀速运行阶段
    if(run_time2 > 0 && target_speed2 > 0) {
        int frequency = target_speed2 * (MAX_FREQUENCY / 255.0);
        printf("Constant speed: %d Hz for %d seconds\n", frequency, run_time2);
        generatePulses(frequency, run_time2 * 1000);
    }
    
    // 减速阶段 - 使用线性减速
    if(decel_time2 > 0 && target_speed2 > 0) {
        int start_freq = target_speed2 * (MAX_FREQUENCY / 255.0);
        linearDecelerate(start_freq, MIN_FREQUENCY, decel_time2 * 1000);
    }
    
    digitalWrite(STEPPER_ENABLE_PIN, HIGH);// 禁用电机
    
    printf("=== Phase 2 Completed ===\n");
    printf("Sequence execution completed\n");
}
void Hx711(char *xb){//======================================================== Hx711称重函数=============================
  //xb = "dt_pin|sck_pin|scale|weight|x|read_times";"6|7|666|500|10|99"
  if('\0' == *xb || NULL == xb) {printf("Hx711(char *xb) '\0' == *xb || NULL ==xb");return;}
  
  char *xbs_str[6]; // 改为5个参数
  unsigned int xbs_int[6]; // 改为5个参数
  u8_t i=6; // 改为5个参数
  
  // 解析参数 S
  while(i){
    if(NULL == (xbs_str[--i] = myStrsep(xb, "|", &xb))){
      printf("debug void Hx711(void *xb) (NULL == pin_dt|pin_sck|scale|weight|x)\r\n");
      return;
    }
    xbs_int[i] = strtol(xbs_str[i],&endptr_fp, 10);
    if (endptr_fp == xbs_str[i]){
      printf("debug Hx711(void *xb) endptr_fp == pin_dt|pin_sck|scale|weight|x,Conversion failed; not a valid number\r\n");
      return;
    }// 转换失败，不是有效的数字
  }// 解析参数 E
  
  int dt_pin = xbs_int[0];
  int sck_pin = xbs_int[1];
  float scale = xbs_int[2];
  int target_weight = xbs_int[3];
  int tolerance = xbs_int[4];
  int max_reads = xbs_int[5];
  
  pinMode(dt_pin, INPUT);
  pinMode(sck_pin, OUTPUT);
  digitalWrite(sck_pin, LOW);
  
  // 计算目标范围
  int min_weight = target_weight - tolerance;
  int max_weight = target_weight + tolerance;
  
  printf("Hx711: Target weight=%d, Tolerance=%d, Range=%d-%d\n", 
         target_weight, tolerance, min_weight, max_weight);
  
  // 循环读取直到达到目标范围
  int read_count = 0;
  
  while(read_count < max_reads) {
    read_count++;
    
    // 带超时的数据就绪等待 S
    unsigned int timeout_ms = 9000;
    unsigned long start_time = millis();
    int consecutive_low = 0;//连续计数器
    const int REQUIRED_CONSECUTIVE = 10; // 需要连续10次检测为低电平       
    while(millis() - start_time < timeout_ms) {
      if(digitalRead(dt_pin) == LOW) {
        consecutive_low++;
        if(consecutive_low >= REQUIRED_CONSECUTIVE) {break;}// 数据就绪，跳出循环
      } else {consecutive_low = 0;} // 重置连续计数器
      delayMicroseconds(10);
    }
    
    if(consecutive_low < REQUIRED_CONSECUTIVE) {
      printf("Hx711(char *xb) Data preparation timeout\r\n");
      continue; // 继续下一次尝试，而不是返回
    }
    //数据就绪 E
    
    //读数据 S
    long data = 0; // 使用long类型，支持负数
    
    for (int i = 0; i < 24; i++) {// 读取24位数据
      digitalWrite(sck_pin, HIGH);
      delayMicroseconds(1);
      data = (data << 1) | digitalRead(dt_pin);
      digitalWrite(sck_pin, LOW);
      delayMicroseconds(1);
    }
    
    // 第25个脉冲设置下一次读取
    digitalWrite(sck_pin, HIGH);
    delayMicroseconds(1);
    digitalWrite(sck_pin, LOW);
    delayMicroseconds(1);    
    
    if (data & 0x800000) {data |= 0xFF000000;}// 符号位处理 (24位有符号数) // 符号扩展
    
    // 数据有效性验证 S - 支持正负值
    // 24位有符号数范围：-8,388,608 到 8,388,607
    if(data == 0 || data < -8388608 || data > 8388607) {
      printf("Hx711(char *xb) read error, data=%ld\r\n", data);
      continue; // 继续下一次尝试，而不是返回
    }// 检查是否为0（可能是误读）// 检查是否在24位有符号数范围内
    // 数据有效性验证 E
    
    float weight = (float)data / scale; // 使用float类型，支持小数和正负值
    int int_weight = (int)weight; // 转换为整数进行比较
    
    printf("Hx711(char *xb) read %d: weight=%.2f, int_weight=%d\r\n", read_count, weight, int_weight);
    
    // 检查是否达到目标范围
    if(int_weight >= min_weight && int_weight <= max_weight) {
      printf("Hx711(char *xb) TARGET REACHED! weight=%d (target=%d±%d)\r\n", 
             int_weight, target_weight, tolerance);
      break; // 达到目标，跳出循环
    }
    
    // 短暂延迟后继续读取
    delay(500);
  }
  
  if(read_count >= max_reads) {
    printf("Hx711(char *xb) MAX READS REACHED without reaching target\r\n");
  }
  
  printf("Hx711(char *xb) completed after %d reads\r\n", read_count);
  //读数据 E
}
void handleNotFound(AsyncWebServerRequest *request) {//======================== webServer未找到页面处理===================
  String message = "文件未找到\n\n";
  message += "URI: ";
  message += request->url();
  message += "\n方法: ";
  message += (request->method() == HTTP_GET) ? "GET" : "POST";
  request->send(404, "text/plain", message);
}
void initWebServer() {//======================================================= Web服务 =================================
  printf("initWebServer S\r\n");
  server.on("/", HTTP_GET,[](AsyncWebServerRequest *request) {//===================== 基本页面路由========
      htttp_request_count++;
      String html = R"=====(
      <!DOCTYPE html>
      <html lang="zh-CN">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>ESP32-S3</title>
        <style>
          #customAlert {/* 弹窗样式 - 可自定义 */
            display: none;position: fixed;top: 20px;left: 50%;transform: translateX(-50%);background: #4CAF50;color: white;padding: 15px 30px;border-radius: 5px;box-shadow: 0 4px 8px rgba(0,0,0,0.2);font-family: Arial, sans-serif;z-index: 1000;animation: fadeIn 0.3s;
          }
        @keyframes fadeIn {/* 关闭动画效果 */
            from {opacity: 0; top: 0;}
            to {opacity: 1; top: 20px;}
          }
        </style>
      </head>
      <body>
      )====="+ firmware_update_btn +R"=====(
        <p>
          <input type="text" placeholder="wifi 名">
          <input type="text" placeholder="wifi 密码">
          <button onclick="submitb(this,'wifiInfo')" type="button">修改</button>         
          <button onclick="getData('wifiInfo')" type="button">获取</button>
        </p>
        <p>
          <input type="text" placeholder="ops">
          <button onclick="submitb(this,'opcombinations')" type="button">发送</button>
        </p>
        <p>
          <input type="text" placeholder="ops" value="4" disabled>
          <input type="number" placeholder="电机X" step="1" min="0" max="7">
          <button onclick="submitb(this,'opcombinations')" type="button">电磁铁1-7</button>
        </p>
        <p>
          <input type="text" placeholder="ops" value="5|12|21" disabled>
          <input type="number" placeholder="方向" step="1" min="0" max="2">
          <button onclick="submitb(this,'opcombinations')" type="button">电机1</button>
        </p>
        <p>
          <input type="text" placeholder="ops" value="5|13|14" disabled>
          <input type="number" placeholder="方向" step="1" min="0" max="2">
          <button onclick="submitb(this,'opcombinations')" type="button">电机2</button>
        </p>
        <p>
          <input type="text" placeholder="ops" value="5|15|16" disabled>
          <input type="number" placeholder="方向" step="1" min="0" max="2">
          <button onclick="submitb(this,'opcombinations')" type="button">电机3</button>
        </p>
        <p>
          <input type="text" placeholder="ops" value="5|17|18" disabled>
          <input type="number" placeholder="方向" step="1" min="0" max="2">
          <button onclick="submitb(this,'opcombinations')" type="button">电机4</button>
        </p>
        <p>
          <input type="text" placeholder="ops" value="6|0" disabled>
          <input type="number" placeholder="角度" step="1" min="0" max="270">
          <input type="number" value="0" disabled>
          <input type="number" value="270" disabled>
          <button onclick="submitb(this,'opcombinations')" type="button">舵机1</button>
        </p>
        <p>
          <input type="text" placeholder="ops" value="6|1" disabled>
          <input type="number" placeholder="角度" step="1" min="0" max="180">
          <input type="number" value="0" disabled>
          <input type="number" value="180" disabled>
          <button onclick="submitb(this,'opcombinations')" type="button">舵机2</button>
        </p>
        <p>
          <input type="text" placeholder="ops" value="6|2" disabled>
          <input type="number" placeholder="角度" step="1" min="0" max="180">
          <input type="number" value="0" disabled>
          <input type="number" value="180" disabled>
          <button onclick="submitb(this,'opcombinations')" type="button">舵机3</button>
        </p>
        <p>
          <input type="text" placeholder="ops" value="6|3" disabled>
          <input type="number" placeholder="角度" step="1" min="0" max="180">
          <input type="number" value="0" disabled>
          <input type="number" value="180" disabled>
          <button onclick="submitb(this,'opcombinations')" type="button">舵机4</button>
        </p>
        <p>
          <input type="text" placeholder="ops" value="7|40|39|38" disabled>
          <input type="number" placeholder="加速步数" step="100" min="0">
          <input type="number" placeholder="最速时间" step="1" min="10">
          <input type="number" placeholder="起步速度" step="1" min="1" max="10">
          <input type="number" placeholder="最大速度" step="1" min="1" max="10">
          <button onclick="submitb(this,'opcombinations')" type="button">步进电机</button>
        </p>
        <button onclick="controlLED('toggle')">切换LED</button>
        <div id="customAlert"></div>
          <script>
            function showAlert(msg, tim = 3000, bgColor = '#4CAF50') {
              const alertBox = document.getElementById('customAlert');
              alertBox.textContent = msg;// 设置内容和样式
              alertBox.style.backgroundColor = bgColor;
              alertBox.style.display = 'block';// 显示弹窗
              if(alertBox.timeoutId) clearTimeout(alertBox.timeoutId);// 清除之前的定时器（避免多次点击冲突）
              alertBox.timeoutId = setTimeout(() => {// 设置新的定时器
                alertBox.style.display = 'none';
              }, tim);
            }           
            async function submitb(ths, info) {
              const parent = ths.parentNode;
              var dt ="";
              const inputs = parent.querySelectorAll('input');              
              Array.from(inputs).map(input => {
                dt += input.value + "|";//encodeURIComponent()
              }).filter(val => val !== null);
              dt=dt.slice(0, -1);
              console.log(dt);
              try {
                const response = await fetch('/'+info, {
                method: 'POST',
                headers: {
                  'Content-Type': 'application/x-www-form-urlencoded',
                  'Authorization': 'Basic ' + btoa('admin:esp32password')
                },
                body: `${info}=${encodeURIComponent(dt)}`
              });
              const text = await response.text();
              //const errorResult = await response.json();//errorResult.msg${errorResult.wf_id}
              showAlert(`${response.status}: ${response.statusText}:${text}`, 3000, "#f44336");
              } catch (error) {
                showAlert(error, 3000, "#f44336");
              }
            }
            async function getData(fn) {
              try {
                const response = await fetch('/readData', {
                method: 'POST',
                headers: {
                  'Content-Type': 'application/x-www-form-urlencoded',
                  'Authorization': 'Basic ' + btoa('admin:esp32password')
                },
                body: `fn=${encodeURIComponent(fn)}`
              });
              const text = await response.text();
              //const errorResult = await response.json();
              showAlert(`${response.status}: ${response.statusText}:${text}`, 3000, "#f44336");
              } catch (error) {
                showAlert(error, 3000, "#f44336");
              }
            }
            function controlLED(action) {
              fetch('/led/' + action)
                .then(response => response.text())
                .then(data => {
                  showAlert(data,3000,"#4CAF50");
                  //location.reload();
                });
            }
          </script>
      </body>
      </html>
      )=====";
      request->send(200, "text/html", html);
  });
  server.on("/opcombinations", HTTP_POST, [](AsyncWebServerRequest *request) {//===== 设备操作============
    if(Q_LEN==q_readable_count){request->send(401, "text/plain", "queue_full");return;}
    const AsyncWebParameter *p = request->getParam(0);
    String valueStr = p->value();
    while(1){//寻找可写队员（queue_a[q_search_writable_i].s为QUEUE_STATUS_WRITABLE
      if(Q_LEN == q_search_writable_i)q_search_writable_i = 0;
			if(QUEUE_STATUS_WRITABLE == ops_queueb[q_search_writable_i].s)break;
			q_search_writable_i++;
		}
    valueStr.toCharArray(ops_queueb[q_search_writable_i].c, sizeof(ops_queueb[q_search_writable_i].c));
    ops_queueb[q_search_writable_i].s = QUEUE_STATUS_READABLE;
    q_search_writable_i++;
    q_readable_count++;
    request->send(200, "text/plain",  debug_info+"xbcb9991");
  });
  server.on("/writeData", HTTP_POST, [](AsyncWebServerRequest *request) {//========== 存储数据==============
    const AsyncWebParameter *p = request->getParam(0);
    String ret = "O";
    if(writeDatab(p->name(),p->value()))ret = "F";
    request->send(200, "application/json", p->value() + " : "+ret);
  });
  server.on("/readData", HTTP_POST, [](AsyncWebServerRequest *request) {//=========== 检索存储的数据=========
    //if(!request->authenticate(www_username, www_password)) {
    //  return request->requestAuthentication();
    //}
    const AsyncWebParameter *p = request->getParam(0);
    if (!SPIFFS.exists("/" + p->value())) {Serial.println("file does not exist");request->send(401, "application/json", "file does not exist");}
    File file = SPIFFS.open("/" + p->value(), "r");
    if (!file) {Serial.println("Unable to open file for reading");request->send(402, "application/json", "Unable to open file for reading");}
    String str = file.readString();
    Serial.println(str);
    file.close();
    request->send(200, "application/json", str);
  });
  server.on("/firmwareupdate", HTTP_GET, [](AsyncWebServerRequest *request) {//====== 固件更新===============
    String str = "b";
    Serial.println("/firmwareupdate");
    startOTAUpdate(otaFirmwareURL + "firmware.bin");
    request->send(200, "application/json", str);
  });
  server.onNotFound(handleNotFound);
  server.begin();
  Serial.println("The HTTP server has been started");// 未找到路由处理
  printf("initWebServer E\r\n");
}
func_ptr functions[] = {
  gpioOutLowHigh,//0
  delayXsecond,//1
  interruptConfg,//2
  delayMs,//3
  setElectromagnet,//4电磁铁控制函数(magnet_pin,bool state)1_1
  setMotor,//5减速电机控制函数(13|14|2)
  smoothMoveServo,//6舵机控制函数(servo_i|target_angle|min_angle|max_angle)
  controlStepperSequence,//7带加速度的步进电机控制
  smoothMoveServob,//8舵机的平滑移动(servo_i|target_angle|min_angle|max_angle|duration)
};
//void isrTask(void *pvParameter) {//============================================ 中断任务 ================================
//  printf("isrTask S\r\n");
//  while(1) {
//    uint32_t notification_value;
//    BaseType_t result = xTaskNotifyWait(0, 0, &notification_value, portMAX_DELAY);// 等待通知（无限等待）
   // if (result == pdTRUE) {// 执行长时间处理
   //   char op_code_copy[256];
   //   strncpy(op_code_copy, isr_struct_b.op_code, sizeof(op_code_copy)-1);
   //   op_code_copy[sizeof(op_code_copy)-1] = '\0';
      
   //   char* xb = op_code_copy;
   //   char *functions_i_str = myStrsep(xb, "|", &xb);
   //   if (NULL == functions_i_str){printf("debug isrTask(void *pvParameter) NULL == functions_i_str\r\n");return;}
   //   u8_t functions_i = (u8_t)strtol(functions_i_str, &endptr_fp, 10);
   //   if (endptr_fp == functions_i_str){printf("debug isrTask(void *pvParameter) endptr_fp == functions_i_str\r\n");return;}// 转换失败，不是有效的数字
   //   fp = functions[functions_i];
   //   fp(xb);// 执行函数
    //  isr_struct_b.trigger_wait = false;
      //vTaskDelay(pdMS_TO_TICKS(1000)); // 让出CPU时间
//    }
  //}
//  printf("isrTask E\r\n");
//}


void isrTask(void *pvParameter) {
  printf("isrTask started - Six-level check debounce mode\n");
  while(1) {
    uint32_t notification_value;
    BaseType_t result = xTaskNotifyWait(0, 0, &notification_value, portMAX_DELAY);
    
    if (result == pdTRUE) {
      // 六次检查都通过后的真正中断处理
      printf("Six-check confirmed valid interrupt: GPIO %d, Opcode: %s\n", 
             isr_struct_b.gpio_num, isr_struct_b.op_code);
      
      // 执行您的实际中断处理逻辑
      // 例如：停止电机、改变方向等
      
      // 处理完成后重新启用中断
      //gpio_intr_enable(isr_struct_b.gpio_num);
      //isr_struct_b.interrupt_enabled = true;
      //isr_struct_b.triggered = false;
      //isr_struct_b.check_phase = 0;
      
      // 清除历史记录
      memset(isr_struct_b.check_times, 0, sizeof(isr_struct_b.check_times));
      memset(isr_struct_b.check_levels, 0, sizeof(isr_struct_b.check_levels));
      isr_struct_b.wait_interrupt  = true;

      vTaskDelay(pdMS_TO_TICKS(100));
    }
  }
}

void setup() {//=============================================================== 系统初始化===============================
  disableCore0WDT();
  disableCore1WDT();
  Serial.begin(115200);
  initGPIO(init_gpios_high);
  initGPIO(init_gpios_low);
  char *pin_level = (char *)"0|0,1|0,2|0,3|1,4|0,5|1";
  gpioOutLowHigh(pin_level);
  initSPIFFS();
  //MySerial.begin(115200, SERIAL_8N1, MY_RX_PIN, MY_TX_PIN);// 启动自定义引脚的串口,SERIAL_8N1: 8位数据位，无校验位，1位停止位（最常用配置）
  Serial.println("Custom UART Started!");// 打印启动信息
  Serial.printf("functions_i::gpioOutLowHigh: 0,delayXsecond: 1,interruptConfg: 2,delayMs: 3");
  Serial.println("\n\n=== ESP32-S3 Web Service startup ===");
  Serial.printf("Chip model: %s\n", ESP.getChipModel());
  Serial.printf("Number of chip cores: %d\n", ESP.getChipCores());
  Serial.printf("SDK version: %s\n", ESP.getSdkVersion());
  Serial.printf("Flash size: %dMB\n", ESP.getFlashChipSize() / (1024 * 1024));
  servos[0].setPeriodHertz(50);servos[1].setPeriodHertz(50);servos[2].setPeriodHertz(50);servos[3].setPeriodHertz(50);
  servos[0].attach(8, 500, 2500);servos[1].attach(9, 500, 2500);servos[2].attach(10, 500, 2500);servos[3].attach(11, 500, 2500);
  initWiFi();// 初始化WiFi
  initMDNS();// 初始化mDNS
  checkFirmwareForUpdate();
  initWebServer();// 初始化Web服务器
  xTaskCreate(isrTask, "isrTask", 8192, NULL, 3, &isr_task_handle);// 创建isrTask处理任务
  gpio_install_isr_service(0);// 安装GPIO ISR服务
  initStepper();// 初始化步进电机
  setOneShotTimer((char *)"3");
  // 闪烁LED表示启动完成
  //for (int i = 0; i < 3; i++) {
  //  digitalWrite(1, LOW);
  //  delay(1000);
  //  digitalWrite(1, HIGH);
  //  delay(1000);
  //}
}
void loop() {//================================================================ 主循环===================================
//  static unsigned long lastUpdate = 0;
//  if (millis() - lastUpdate >= 10000) {// 每10秒更新系统状态
//    lastUpdate = millis();
    // 打印系统状态
//    Serial.printf("[system state] Memory: %dKB | WiFi: %d%% | request: %d", ESP.getFreeHeap() / 1024,map(WiFi.RSSI(), -100, -40, 0, 100),htttp_request_count);
//    Serial.println("");
//  } 
//  delay(10);// 短暂延迟
  while(q_readable_count){//寻找可读队员（ops_queueb[q_search_readable_i].s为QUEUE_STATUS_READABLE
    if(Q_LEN == q_search_readable_i)q_search_readable_i = 0;//最后队号不可读但可读队员数不为0时，从头开始寻找可读队员，如此往复
    if(QUEUE_STATUS_WRITABLE == ops_queueb[q_search_readable_i].s){q_search_readable_i++;continue;}//跳过可写队员
      Serial.printf("q_readable_count %d Start processing ops_queueb[%d] %s\r\n",q_readable_count,q_search_readable_i,ops_queueb[q_search_readable_i].c);
      next_p = ops_queueb[q_search_readable_i].c;
      while(next_p){
        temp = myStrsep(next_p, "_",&next_p);
        functions_i = strtol(myStrsep(temp,"|",&temp_next_p), &endptr_fp, 10);
        fp = functions[functions_i];
        fp(temp_next_p);// 执行函数
      }
      //printf("ops_queueb[%d] processing completed",q_search_readable_i);
      ops_queueb[q_search_readable_i].s = QUEUE_STATUS_WRITABLE;
      q_search_readable_i++;
      q_readable_count--;
	}
  //if (MySerial.available()) {
  //  String receivedData = MySerial.readStringUntil('\n'); // 读取直到换行符 // 1. 从自定义串口读取数据并打印到调试串口
  //  Serial.print("Received: ");
  //  Serial.println(receivedData);
  //}
 // static unsigned long lastSend = 0;
 // if (millis() - lastSend > 2000) {// 2. 每隔2秒通过自定义串口发送一个消息
 //   lastSend = millis();
 //   MySerial.println("Hello from ESP32-S3 MySerial!");
 //   Serial.println("Message sent via custom UART.");
 // }
}